/********************************************************************************
 *      Copyright:  (C) 2025 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  pack.hpp
 *    Description:  This file
 *
 *        Version:  1.0.0(29/09/25)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "29/09/25 14:31:38"
 *                 
 ********************************************************************************/

#ifndef _PACK_H_
#define _PACK_H_

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <stdexcept>
#include <cstring>
#include <algorithm>
#include <memory>

#include "get_temp.hpp"

namespace IotClient {

constexpr int DEVID_LEN = 8;
constexpr uint16_t TLV_HEADER = 0xFEED;
constexpr int TLV_MINISIZE = 7;
constexpr uint16_t CRC16_ITU_T_POLY = 0X1021;

//强类型枚举：可用来隔离作用域，必须使用TagType::TEMPERATURE形式来访问，减少冲突
//传统的enum可以隐式转换为整数，而enum class不能隐式转换为整数，增强了类型安全
enum class TagType : uint8_t
{
    TEMPERATURE = 1,
    HUMIDITY,
    NOISY
};

struct SensorData
{
    std::string systime;
    std::string id;
    float temp_value;
};

class DataCollector
{
public:
    //引用，sensor_ (成员变量)	(sensor) (输入参数)	将外部传进来的 sensor 引用，用来初始化内部的 sensor_ 成员引用
    //保证了DataCollector对象在创建时，不创建Ds18b20Sensor 和 SystemInfo 的副本。
    //而是安全地链接到外部已经存在的、负责数据获取的sensor和sysinfo对象
    DataCollector(Ds18b20Sensor& sensor, SystemInfo& sysInfo) : sensor_(sensor), sysInfo_(sysInfo) {}

    SensorData collectData();

private:
    Ds18b20Sensor& sensor_;
    SystemInfo& sysInfo_;
};

class DataPacker
{
public:
    virtual ~DataPacker() = default; //虚函数(允许派生类覆盖这个函数)，virtual启用运行时多态

    //=0:纯虚函数标记，告诉编译器：
    //这个函数没有实现；包含这个函数的类是一个抽象基类，不能被直接实例化
    //任何非抽象的派生类都必须提供自己的pack函数实现
    //定义一个统一的、强制性的接口，可以实现三种数据打包方式
    virtual std::vector<uint8_t> pack(const SensorData& data) const = 0;
};

//分段打包
class SegmentPacker : public DataPacker
{
public:
    std::vector<uint8_t> pack(const SensorData& data) const override;
private:
    const char DELIMITER = '+';
};

//JSON格式
class JsonPacker : public DataPacker
{
public:
    std::vector<uint8_t> pack(const SensorData& data) const override;
};

//TLV格式(CRC辅助)
class TlvPacker : public DataPacker
{
public:
    std::vector<uint8_t> pack(const SensorData& data) const override;
private:
    static uint16_t to_big_endian(uint16_t num);
    static uint16_t crc_itu_t(const uint8_t *data, size_t length);
};

}

#endif
